/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package FACTURAS;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.StringTokenizer;

/**
 *
 * @author VICENTE
 */
public class CodigoControl {

    private String numAutorizacion;
    private String numFactura;
    private String nitCliente;
    private String fecha;
    private String monto;    
    private String llave;

    public CodigoControl(String llave, String autorizacion, String numFactura, String nitCliente, String fecha_emision, String monto){

        this.llave = llave;
        this.numAutorizacion = autorizacion;
        this.numFactura = numFactura;
        this.nitCliente = nitCliente;
        this.fecha = fecha_emision;

        BigDecimal big = new BigDecimal(Double.valueOf(monto));
        Double total = big.setScale(0, RoundingMode.HALF_UP).doubleValue();
        String valor = String.valueOf(total);
        StringTokenizer i = new StringTokenizer(valor,".");
        this.monto = i.nextToken();        
                
    }

    public String generarCodigoControl() {

        //PASO 1
        //obtener y concatenar consecutivamente dos numeros verhoeff al final de los siguientes datos
        String numFacV    = concatenarNVerhoeff(numFactura, 2).trim();//numero de factura
        String nitV       = concatenarNVerhoeff(nitCliente, 2).trim();//nit del cliente
        String fechaV     = concatenarNVerhoeff(fecha, 2).trim();//fecha de transaccion
        String montoV     = concatenarNVerhoeff(monto, 2).trim();//monto de la transaccion

        //sumatoria de los datos obtenidos
        Long sum = Long.valueOf(numFacV)+Long.valueOf(nitV)+Long.valueOf(fechaV)+Long.valueOf(montoV);

        String aux = concatenarNVerhoeff(String.valueOf(sum), 5);//sumaroria mas cinco numeros verhoeff a partir de la sumatoria de datos obtenidos en el paso anterior
        String digitosVerhoeff = aux.substring(aux.length()-5, aux.length());//cadena con los cinco numeros verhoeff

        // PASO 2
        int [] digitosVerhoeffSum = StringToIntArray(digitosVerhoeff);//array de los cinco digitos verhoeff sumados uno
        String[] listCadenas = new String[5];

        int inicioCadena = 0;
        for(int i=0; i<5;i++){
            //recuperar de la Llave de Dosificación 5 cadenas adyacentes, cada una con un largo definido por el dígito Verhoeff correspondiente más 1
            listCadenas[i] = llave.substring(inicioCadena,digitosVerhoeffSum[i]+inicioCadena);
            inicioCadena = inicioCadena + digitosVerhoeffSum[i];
        }
        listCadenas[0] = numAutorizacion+listCadenas[0];//Concatenar la primera cadena obtenida al final del dato relacionado al Número de Autorización
        listCadenas[1] = numFacV+listCadenas[1];//Concatenar la segunda cadena co nel numero de factura
        listCadenas[2] = nitV+listCadenas[2];//Concatenar la tercera cadena con el nit del cliente
        listCadenas[3] = fechaV.concat(listCadenas[3]);
        listCadenas[4] = montoV.concat(listCadenas[4]);

        // PASO 3

        String cadenaConcatenada = listCadenas[0]+listCadenas[1]+listCadenas[2]+listCadenas[3]+listCadenas[4];
        String allegedrc4 = Allegedrc4.encriptaSinguion(cadenaConcatenada, llave + digitosVerhoeff);

        // PASO 4
        int[] asciiDigitos = cambiarDigitosaInt(allegedrc4);
        int[] sumasParciales = new int[5];
        int sumaDigitos = 0;
        sumasParciales[4] = 0;
        for(int i=0;i<asciiDigitos.length;i++){
            sumaDigitos = sumaDigitos + (int) allegedrc4.charAt(i);
            if(i%5 == 0){
                sumasParciales[0] = sumasParciales[0] + asciiDigitos[i];
            }else if((i+4)%5 ==0){
                sumasParciales[1] = sumasParciales[1] + asciiDigitos[i];
            }else if((i+3)%5 == 0){
                sumasParciales[2] = sumasParciales[2] + asciiDigitos[i];
            }else if((i+2)%5 == 0){
                sumasParciales[3] = sumasParciales[3] + asciiDigitos[i];
            }else if((i+1)%5 == 0){
                sumasParciales[4] = sumasParciales[4] + asciiDigitos[i];
            }
        }

        //  PASO 5
        int sumaTotal = 0;
        for(int i =0;i<5;i++){
            sumasParciales[i]= (sumaDigitos * sumasParciales[i])/ digitosVerhoeffSum[i];
            sumaTotal = sumaTotal+sumasParciales[i];
        }

        String coded = DecimalToBase64.covertirBase64(sumaTotal);
        //  PASO 6
        String codigoControl = Allegedrc4.encripta(coded, llave+digitosVerhoeff);
        return codigoControl;
    }


    private int[] StringToIntArray(String num){

        int[] myArray = new int[num.length()];
        for(int i = 0; i < num.length(); i++){
                myArray[i] = Integer.parseInt(num.substring(i, i + 1))+1;
        }
        return myArray;

    }

    private String concatenarNVerhoeff(String num, int cantidad){
        String numero = num;
        for(int i=1;i<= cantidad;i++){
            numero = numero + Verhoeff.generateVerhoeff(numero);
        }
        return numero;
    }

    private int[] cambiarDigitosaInt(String allegedrc4) {
        int[] resultado = new int[allegedrc4.length()];
        for(int i=0; i<allegedrc4.length();i++){
            resultado[i] = (int) allegedrc4.charAt(i);

        }
        return resultado;
    }

    public static void main(String args[]) {
        CodigoControl cod = new CodigoControl(null, null, null, null, null, null);
    }
}
